import {
  useCallback,
  useImperativeHandle,
  forwardRef,
  useMemo,
  useState,
  useEffect,
  ForwardedRef,
} from 'react';
import {
  InfiniteScroll,
  SearchBar,
  PullToRefresh,
  FloatingBubble,
} from 'antd-mobile';
import { IntlProvider } from 'react-intl';
import zhCN from './locales/zh-CN';
import enUS from './locales/en-US';
import _zhCN from './locales/zh-CN';
import './index.less';
import useListRequest, {
  queryData,
  queryChildData,
} from '../../designer/wap/useListRequest';
import { useEvents } from '@inbiz/utils';
import { useFieldSchema } from '@formily/react';
import { Route, Routes, useLocation } from 'react-router-dom';
import DataItem from './DataItem';
import DataDetails, { DetailPage } from './DataDetails';
import { AddOutline } from 'antd-mobile-icons';
import api from './api';
import type { queryDataInfo } from './service';
import { TablePreviewProps } from '../../interfaces';
import { connect, mapProps } from '@formily/react';
import { hasAuth } from '@inbiz/basic/AuthForm';
import { useInbizRouter } from '@inbiz/hooks';
const messages = {
  'zh-CN': { ...zhCN, ..._zhCN },
  'en-US': { ...enUS },
};
import { inbiz } from '@inbiz/core';
import { TextWidget, getMessage } from '@inbiz/react';

export type IdefaultProps = {
  emit: {
    (type: 'oncustom', action: object, data: object): void;
    (type: 'onread', action: object, data: object): void;
    (type: 'onedit', action: object, data: object): void;
    (type: 'ondelete', data: object): void;
    (type: 'onload'): void;
    (type: 'onupdateItem', data: object, optiontype: string): void;
  };
  callBackEvents: {
    onBeforeOperationAsync?: (
      action: object,
      data?: object,
    ) => boolean | Promise<boolean>;
    onParamFormat?: <T>(param: T) => T;
    onDataLoad?: <T>(data: T) => T;
    onRequest?: typeof queryData;
    onChildParamFormat?: <T>(param: T) => T;
    onChildDataLoad?: <T>(data: T) => T;
    onChildRequest?: typeof queryChildData;
    onOpenChildUrl?: (action?: object, data?: object) => object;
    onDataEdited?: typeof queryDataInfo;
  };
  inbiz: inbiz;
};

const Table = forwardRef((props: TablePreviewProps, ref: ForwardedRef<any>) => {
  //@ts-ignore
  const appId = props?.inbiz.appInfo.appId;
  //@ts-ignore
  const { queryFields, tableValues, formItems, auth } = props.columnConfig;
  const { actions, attrs } = tableValues;
  const [showFields, $showFields] = useState(
    () => attrs?.map((item: any) => {
      const data =  {
        ...queryFields?.filter((item1: any) => {
          return item1.value == item.propName;
        })[0],
        title: item.columnName ? item.columnName : item.propName,
      };
      if (data.value === undefined) {
        data.value = item.propName
      }
      return data
    }) || [],
  );
  const [configEvents] = useEvents(props.callBackEvents, props.emit);
  const filedShcema = useFieldSchema()

  const tableId = filedShcema?.['x-designable-id'];
  const [queryData, $queryData] = useState([]);
  const modelKeyName = props.primarykey || 'id';
  // 保存所有加载的数据
  const [dataList, $dataList] = useState<{
    hasMore: boolean;
    total: number;
    pageIndex: number;
    searchValue?: string;
    list: {
      [key: string]: string | number | boolean | object | object[];
    }[];
  }>({
    list: [],
    pageIndex: 0,
    total: 0,
    hasMore: false,
  });
  useImperativeHandle(
    ref,
    () => {
      return {
        ...api(
          configEvents,
          props,
          dataList,
          $dataList,
          $queryData,
          showFields,
          $showFields,
        ),
      };
    },
    [props, dataList, $dataList, showFields],
  );
  // 详情页面对dataList进行更新问题
  const handleChangeListData = useCallback(
    (type, resultData, id) => {
      $dataList((data) => {
        if (type === 'eformtableedit' && id && resultData) {
          const list = [...data.list];
          const index = data.list.findIndex((item) => item[modelKeyName] == id);
          list[index] = { ...list[index], ...resultData };
          return {
            ...data,
            list,
          };
        }
        if (type === 'eformtableadd' && id && resultData) {
          return {
            ...data,
            total: data.total + 1,
            list: [...data.list, { ...resultData, [modelKeyName]: id }],
          };
        }
        if (type === 'eformtabledel' && id) {
          const list = [...data.list];
          const index = data.list.findIndex((item) => item[modelKeyName] == id);
          list.splice(index, 1);
          return {
            ...data,
            total: data.total - 1,
            list: list,
          };
        }
        return data;
      });
    },
    [showFields],
  );

  // 请求数据接口
  //@ts-ignore
  const { runAsync, error } = useListRequest(
    configEvents,
    undefined,
    props.emit,
  );
  // 子表是否懒加载
  const filterLazy = useMemo(() => {
    if (showFields) {
      return showFields
        .filter((item: any) => item.IsMany)
        .map((item: any) => {
          if (!item.relation || item.relation.showType === '1') {
            return item.field;
          } else {
            return '';
          }
        })
        .filter((item: any) => !!item)
        .join(',');
    } else {
      return '';
    }
  }, [showFields]);
  // 获取数据方法
  const getData = useCallback(
    async ({
      pageIndex = 1,
      searchValue,
      list,
      total,
      hasMore,
    }: {
      pageIndex?: number;
      searchValue?: string;
      list?: [];
      total?: number;
      hasMore?: boolean;
    } = {}) => {
      if (props.sourceModel && appId || configEvents.current.onRequest) {
        $dataList((data) => ({
          ...data,
          hasMore: hasMore === undefined ? data.hasMore : hasMore,
          pageIndex,
          searchValue,
          list: list || data.list,
          total: total === undefined ? data.total : total,
        }));
        let index = 0;

        let sendParam = {
          pageIndex: queryData.length ? 1 : pageIndex,
          pageSize: formItems?.pageSize || 10,
          appId: appId,
          filterLazy,
          key: props.sourceModel,
          conditions:
            searchValue && props.search
              ? queryData
                ? [
                  {
                    index,
                    connector: 'and' as const,
                    condition: [
                      {
                        connector: 'and' as const,
                        operator: 'like' as const,
                        field: formItems.searchFiled,
                        value: searchValue,
                      },
                    ],
                  },
                ].concat(
                  queryData?.map((item: any) => {
                    return {
                      ...item,
                      index: ++index,
                    };
                  }),
                )
                : [
                  {
                    index,
                    connector: 'and' as const,
                    condition: [
                      {
                        connector: 'and' as const,
                        operator: 'like' as const,
                        field: formItems.searchFiled,
                        value: searchValue,
                      },
                    ],
                  },
                ]
              : queryData
                ? queryData?.map((item: any) => {
                  return {
                    ...item,
                    index: ++index,
                  };
                })
                : [],
        };
        return runAsync(sendParam).then((data) => {
          if (data?.Rows) {
            if (data.primary && data.primary != 'id') {
              data.Rows.forEach(item => {
                if (item?.id === undefined && item?.[data.primary!]) {
                  item.id = item[data.primary!]
                }
              })
            };
            $dataList((dataList) => {
              const newData = {
                ...dataList,
                total: data.Total,
                list: data.Rows,
                hasMore: data.Rows.length >= sendParam.pageSize,
              };
              if (dataList.list?.length) {
                // 过来重复的数据
                const list = [...dataList.list];
                data.Rows.forEach((row) => {
                  const isAdd = !list.find(
                    (item) => item[modelKeyName] == row[modelKeyName],
                  );
                  if (isAdd) {
                    list.push(row);
                  }
                });
                newData.list = list;
              }
              return newData;
            });
          } else {
            $dataList((dataList) => ({ ...dataList, hasMore: false }));
          }
        });
      } else {
        return Promise.resolve();
      }
    },
    [props.search, props.sourceModel, appId, filterLazy, queryData],
  );

  // 首次加载数据
  useEffect(() => {
    if (props.autoLoad) {
      getData({}).then((res) => {
        props.emit?.('onload');
      });
    }
  }, [queryData, props.autoLoad]);
  // 下拉加载
  const loadMore = useCallback(() => {
    return getData({
      pageIndex: dataList.pageIndex + 1,
      searchValue: dataList.searchValue,
    });
  }, [dataList.pageIndex, dataList.searchValue]);
  // 配置显示的列
  const columns = useMemo(() => {
    if (showFields) {
      return showFields.map((item: any) => {
        if (item.title === undefined) {
          const title = item.field?.split('$')[1] || item.field;
          return { ...item, title };
        } else {
          return item as { title: string; field: string };
        }
      });
    } else {
      return [];
    }
  }, [showFields]);
  const history = useInbizRouter();
  const { pathname } = history.location;

  const pagePath = useMemo(() => {
    return pathname + '/inbizsubroute';
  }, []);

  const goDetail = useCallback(
    async (data) => {
      //@ts-ignore
      if (props.inbiz.browser.designer) {
        return;
      }

      const editOperation = actions.find((item: any) => item.actionType === 'edit');
      const authFlag = hasAuth(
        {
          table: [
            { ...editOperation, operationType: editOperation?.actionType },
          ],
          auth: auth,
        },
        'edit',
        props.inbiz?.auth,
      ).auth;
      if (editOperation?.page && authFlag) {
        props.emit?.('onClick', 'edit', editOperation, data);
        const result = await configEvents.current?.onBeforeOperationAsync?.(
          editOperation,
          data,
        );
        if (result === false) {
          return;
        }

        props.emit?.('onOpen', editOperation, data);
        const urlData = configEvents.current?.onOpenChildUrl?.(
          editOperation,
          data,
        );
        //@ts-ignore
        history.push({
          pathname:
            pagePath +
            `/${tableId}/eformtabledetails/` +
            `eformtable${editOperation.actionType}`,
          //@ts-ignore
          query: {
            id: data[modelKeyName],
            pageRout: editOperation.page?.split(',')[0],
            ...urlData,
          },
        });
      } else {
        // props.emit?.('onClick', 'view');
        //@ts-ignore
        history.push({
          pathname: pagePath + `/${tableId}/eformtabledetails`,
          query: { id: data[modelKeyName] },
        });
      }
    },
    [modelKeyName, actions],
  );

  const ChildRoutes = useMemo(function () {
    const query = history.location.query;
    const item = dataList.list.find((item) => item[modelKeyName] == query?.id) || [];
    return <Routes>
      <Route path={`/${tableId}/eformtabledetails`} element={
        <DataDetails
          operations={actions}
          modelKeyName={modelKeyName}
          events={configEvents}
          list={dataList.list}
          inbiz={props.inbiz!}
          emit={props.emit}
          updateList={handleChangeListData}
          auth={auth}
          modelKey={props.modelkey!}
          modelname={props.modelname}
        >
          <DataItem
            key={`${pagePath}_${query?.id}`}
            pagePath={pagePath}
            columns={columns}
            data={item}
            isCard={false}
            showDetail={false}
            history={history}
            radiusStyle={props.style?.borderRadius} modelname={''} />
        </DataDetails>
      }>
        <Route
          path={':type'}
          element={<DetailPage
            events={configEvents}
            inbiz={props.inbiz}
            emit={props.emit}
            updateList={handleChangeListData}
            filterLazy={filterLazy}
            appId={appId}
            sourceModel={props.sourceModel!}
          />}
        />
      </Route>
    </Routes>
  }, [
    dataList.list,
    actions,
    filterLazy,
    props.sourceModel,
    queryData,
    auth,
    history.location.query,
    props.style?.borderRadius
  ])

  // 点击搜索
  const handleSearch = useCallback(
    (value?: string) => {
      if (dataList.searchValue != value) {
        $dataList((data) => ({
          ...data,
          list: [],
          total: 0,
          pageIndex: 0,
          searchValue: value ? value.trim() : '',
          hasMore: true,
        }));
      }
    },
    [dataList.searchValue],
  );
  // 下拉刷新
  const handleRefresh = useCallback(() => {
    if (props.autoLoad) {
      $dataList((data) => ({
        ...data,
        list: [],
        total: 0,
        pageIndex: 0,
        hasMore: true,
      }));
    }
    return Promise.resolve();
  }, [dataList.searchValue, props.autoLoad]);
  // 创建数据
  const isShowAddButton = useMemo(() => {
    const editOperation = actions.find(
      (item: any) => item.actionType === 'add',
    );
    const authFlag = hasAuth(
      {
        table: [{ ...editOperation, operationType: editOperation?.actionType }],
        auth: auth,
      },
      'add',
      props.inbiz?.auth,
    ).auth;
    return !!editOperation?.page?.split(',')[0] && authFlag;
  }, [actions, props.inbiz?.auth, auth]);

  const handleAdd = useCallback(async () => {
    const operation = actions.find((item: any) => item.actionType === 'add')!;
    props.emit?.('onClick', 'add', operation);
    const result = await configEvents.current.onBeforeOperationAsync?.(
      operation!,
    );
    if (result === false) {
      return;
    }
    props.emit?.('onOpen');
    const urlData = configEvents.current.onOpenChildUrl?.(operation);
    history.push({
      pathname: pagePath + `/${tableId}/eformtabledetails/eformtableadd`,
      query: { pageRout: operation.page?.split(',')[0], ...urlData }
    });
  }, [actions, pagePath]);
  const itemList = useMemo(() => {
    return dataList.list.map((item) => (
      <DataItem
        isSwipeAction
        options={actions}
        history={history}
        pagePath={pagePath}
        inbiz={props.inbiz}
        modelKey={props.modelkey}
        columns={columns}
        data={item}
        key={item.id as string}
        onClick={goDetail}
        updateList={handleChangeListData}
        showRow={4}
        events={configEvents}
        emit={props.emit}
        //@ts-ignore
        auth={auth}
        modelname={props.modelname}
        radiusStyle={props.style?.borderRadius}
      />
    ));
  }, [dataList, columns, auth, props.style?.borderRadius]);
  return (
    <IntlProvider locale={'zh-CN'} messages={messages['zh-CN']}>
      {ChildRoutes}
      <div className={`eformDataGrid ${props.className || ''}`}>
        {props.search && formItems.searchFiled && (
          <div className="searchBox">
            <SearchBar
              placeholder={props.searchPlacehoder}
              onSearch={handleSearch}
              onCancel={handleSearch}
              onClear={handleSearch}
              clearOnCancel
            />
          </div>
        )}
        <div className="content">
          <PullToRefresh
            onRefresh={handleRefresh}
            pullingText={getMessage('Table.pullDownRefresh')}
            completeText={getMessage('Table.refreshSucceeded')}
            canReleaseText={getMessage('Table.releaseRefreshNow')}
            refreshingText={getMessage('Table.loading} >')}
          >
            <div className="total">
              <TextWidget>Table.common</TextWidget>
              {dataList.total}
              <TextWidget>Table.strip</TextWidget>
            </div>
            {itemList}
            <InfiniteScroll
              loadMore={loadMore}
              hasMore={error ? false : dataList.hasMore}
            >
              <TextWidget>Table.noMore</TextWidget>
            </InfiniteScroll>
          </PullToRefresh>
        </div>
        {isShowAddButton && (
          <FloatingBubble
            style={{
              '--initial-position-bottom': '60px',
              '--initial-position-right': '20px',
            }}
            onClick={handleAdd}
          >
            <div className="addButton">
              <AddOutline />
            </div>
          </FloatingBubble>
        )}
      </div>
    </IntlProvider>
  );
});

Table.displayName = 'EformDataGrid';

export default connect(
  Table,
  mapProps({}, function (props, field) {
    return {
      ...props,
      boxHeight: field.decoratorProps?.style?.height,
      searchPlacehoder: props.searchPlacehoder
        ? getMessage(props.searchPlacehoder)
        : getMessage('Table.pleaseEnterTheSearchContent'),
    };
  }),
);
